#include <bits/stdc++.h>

#define eb emplace_back
#define fi first
#define se second
#define in read<int>()
#define lin read<ll>()
#define rep(i, x, y) for(int i = (x); i <= (y); i++)
#define per(i, x, y) for(int i = (x); i >= (y); i--)
#define epr(i, x, y) for(int i = h[x], y = e[i].v; i; i = e[i].nxt, y = e[i].v)
#define eepr(i, G, x, y) for(int i = G.h[x], y = G.e[i].v; i; i = G.e[i].nxt, y = G.e[i].v)

using namespace std;

using ll = long long;
using pii = pair < int, int >;
using vec = vector < int >;

template < typename T > T read() {
	T x = 0; bool f = 0; char ch = getchar();
	while(!isdigit(ch)) f |= ch == '-', ch = getchar();
	while(isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar();
	return f ? -x : x;
}

const int N = 1e5 + 10;
const int K = 18;

int n;
ll val[N], ans = -4e18; // only true dots need.
int tg[N];
bool v[N << 2];

int stk[N], top;

template < int N, int M, int TN > struct graph {
	int lg[TN], pw[K + 10], mn[K + 1][TN];
	int dep[N], dfn[N], n, tot, cnt, h[N], siz[N]; ll tdep[N], rdis[N];
	int rt, res;
	vector < pair < int, ll > > G[N];
	struct edge { int v; ll w; int nxt; } e[M];
	graph() { cnt = 1; }
	void reset() { cnt = 1; rep(i, 1, n) h[i] = 0; } 
	void link(int x, int y, ll w) { e[++cnt] = (edge) { y, w, h[x] }; h[x] = cnt; }
	void alink(int x, int y, ll w) { link(x, y, w); link(y, x, w); }
	void tlink(int x, int y) { /*notice!*/ link(x, y, tdep[y] - tdep[x]); }
	int tmn(const int &x, const int &y) { return dep[x] < dep[y] ? x : y; }
	int tcalc(int l, int r) { int k = lg[r - l + 1]; return tmn(mn[k][l], mn[k][r - pw[k] + 1]); } // g2, g3
	int lca(int x, int y) { return (dfn[x] > dfn[y]) && (swap(x, y), 1), tcalc(dfn[x], dfn[y]); } // g2, g3
	void dfs(int x, int p) { dep[x] = dep[p] + 1; mn[0][dfn[x] = ++tot] = x; epr(i, x, y) if(y ^ p) tdep[y] = tdep[x] + e[i].w, dfs(y, x), mn[0][++tot] = x; } // enable in g2, g3.
	ll dis(int x, int y) { return tdep[x] + tdep[y] - tdep[lca(x, y)] * 2; }
	void ddfs(int x, int p) { epr(i, x, y) if(y ^ p && !v[i >> 1]) rdis[y] = rdis[x] + e[i].w, ddfs(y, x); }
	void edfs(int x, int p) { epr(i, x, y) if(y ^ p) edfs(y, x), G[x].eb(y, e[i].w); } // enable in g1.
	void init() { // set lca, enable in g2, g3.
		dfs(1, 0); rep(i, 2, tot) lg[i] = lg[i >> 1] + 1; pw[0] = 1; rep(i, 1, K) pw[i] = pw[i - 1] * 2;
		rep(k, 1, K) rep(i, 1, tot - pw[k] + 1) mn[k][i] = tmn(mn[k - 1][i], mn[k - 1][i + pw[k - 1]]);
		reset();
	}
	void virtual_build(const vec &pot) {
		stk[top = 1] = 1;
		for(auto x : pot) {
			if(x == 1) continue; int L = lca(x, stk[top]);
			while(top > 1 && dfn[L] <= dfn[stk[top - 1]]) tlink(stk[top - 1], stk[top]), top--;
			if(stk[top] != L) tlink(L, stk[top]), stk[top] = L;
			stk[++top] = x;
		} rep(i, 2, top) tlink(stk[i - 1], stk[i]);
	}
	void rebuild() { // enable in g1.
		edfs(1, 0); reset(); 
		rep(x, 1, n) {
			if(G[x].size() <= 2) for(auto v : G[x]) alink(x, v.fi, v.se);
			else {
				int t1 = ++n, t2 = ++n; alink(x, t1, 0); alink(x, t2, 0);
				for(auto v : G[x])
					if(G[t1].size() < G[t2].size()) G[t1].eb(v);
					else G[t2].eb(v);
			} vector < pair < int, ll > >().swap(G[x]);
		}
	}
	void frt(int x, int p, int tsiz) {
		siz[x] = 1;
		epr(i, x, y)
			if(!v[i >> 1] && y ^ p) frt(y, x, tsiz), (max(siz[y], tsiz - siz[y]) < res) && (res = max(siz[y], tsiz - siz[y]), rt = i), siz[x] += siz[y];
	}
	vec divide(int x, int tsiz);
};

graph < N << 2, N << 3, 1 > g1;
graph < N, N << 1, N << 1 > g2, g3;

ll calc(pii t) { return val[t.fi] + val[t.se] + g3.dis(t.fi, t.se); }

vec tmerge(const vec &a, const vec &b) {
	auto ita = a.begin(), itb = b.begin(); vec res;
	while(ita != a.end() && itb != b.end()) res.eb(g2.dfn[*ita] < g2.dfn[*itb] ? *ita++ : *itb++);
	while(ita != a.end()) res.eb(*ita++); while(itb != b.end()) res.eb(*itb++);
	return res;
}

pii amerge(pii a, pii b) {
	pii res = { 0, 0 }; ll v = calc(res), cur;
	if((cur = calc({ a.fi, b.fi })) >= v) v = cur, res = { a.fi, b.fi };
	if((cur = calc({ a.fi, b.se })) >= v) v = cur, res = { a.fi, b.se };
	if((cur = calc({ a.se, b.fi })) >= v) v = cur, res = { a.se, b.fi };
	if((cur = calc({ a.se, b.se })) >= v) v = cur, res = { a.se, b.se };
	return res;
}

pii operator + (pii a, pii b) {
	pii res = amerge(a, b); ll v = calc(res), cur;
	if((cur = calc(a)) >= v) v = cur, res = a; if((cur = calc(b)) >= v) v = cur, res = b;
	return res;
}

pair < pii, pii > work(int x, ll exw) {
	pair < pii, pii > res = { { 0, 0 }, { 0, 0 } };
	if(tg[x] == 1) res.fi = { x, 0 }; if(tg[x] == 2) res.se = { x, 0 };
	eepr(i, g2, x, y) {
		auto t = work(y, exw);
		ans = max(ans, calc(amerge(res.fi, t.se)) - g2.tdep[x] * 2 + exw); ans = max(ans, calc(amerge(res.se, t.fi)) - g2.tdep[x] * 2 + exw);
		res.fi = res.fi + t.fi; res.se = res.se + t.se;
	} return res;
}

void cldfs(int x) { eepr(i, g2, x, y) cldfs(y); tg[x] = 0; g2.h[x] = 0; }

template < int N, int M, int TN > vec graph < N, M, TN > :: divide(int x, int tsiz) {
	rt = 0; res = 1e9; frt(x, 0, tsiz);
	if(res == 1e9) return x <= ::n ? vec(1, x) : vec(0);
	int y = e[rt].v, id = rt; ll exw = e[id].w; x = e[rt ^ 1].v; v[id >> 1] = 1;
	if(siz[x] > siz[y]) swap(x, y); int asiz = siz[x], bsiz = tsiz - siz[x];
	vec t1 = divide(x, asiz), t2 = divide(y, bsiz); 
	for(auto v : t1) tg[v] = 1; for(auto v : t2) tg[v] = 2;
	vec res = tmerge(t1, t2); g2.virtual_build(res);
	rdis[x] = rdis[y] = 0; ddfs(x, 0); ddfs(y, 0); for(auto v : res) val[v] = rdis[v] + g2.tdep[v];
	work(1, exw); cldfs(1); g2.cnt = 1; v[id >> 1] = 0;
	return res;
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("1.in", "r", stdin);
#endif
	g1.n = g2.n = g3.n = n = in;
	rep(i, 2, n) { int u = in, v = in; ll w = lin; g1.alink(u, v, w); }
	g1.rebuild(); rep(i, 2, n) { int u = in, v = in; ll w = lin; g2.alink(u, v, w); }
	rep(i, 2, n) { int u = in, v = in; ll w = lin; g3.alink(u, v, w); }
	g2.init(); g3.init(); g1.divide(1, g1.n); rep(i, 1, n) ans = max(ans, g1.dep[i] + g2.dis(1, i) + g3.dis(1, i)); printf("%lld\n", ans);
	return 0;
}
